#include "ExpAST.h"
#include "Globe.h"
#include <iostream>
#include "parser.h"
#include "Globe.h"
#pragma warning(disable:4267)
using std::cout;
using std::endl;

unique_ptr<BaseExpAST> parser::parseRelExp()
{
    unique_ptr<BaseExpAST>l = this->parseShiftExp();
    while (this->lexer->next_token() == TOK::GT || this->lexer->next_token() == TOK::GE || this->lexer->next_token() == TOK::LT || this->lexer->next_token() == TOK::LE)
    {
        unique_ptr<RelAST>t(new RelAST);
        switch (this->lexer->next_token())
        {
        case TOK::GT:
            t->op = RelAST::GT;
            break;
        case TOK::GE:
            t->op = RelAST::GE;
            break;
        case TOK::LT:
            t->op = RelAST::LT;
            break;
        case TOK::LE:
            t->op = RelAST::LE;
            break;
        default:
            break;
        }
        this->lexer->match(this->lexer->next_token());
        t->exp1 = std::move(l);
        t->exp2 = this->parseShiftExp();
        l = std::move(t);
        t = nullptr;
    }
    return l;
}

void RelAST::Dump() const
{
    cout << "{\"type\":\"Rel\",\"op\":\"";
    switch (this->op)
    {
    case GT:
        cout << ">";
        break;
    case GE:
        cout << ">=";
        break;
    case LT:
        cout << "<";
        break;
    case LE:
        cout << "<=";
        break;
    default:break;
    }
    cout << "\"";
    if (this->op == DEFAULT)
    {
        cout << "\"content\":";
        this->exp1->Dump();
    }
    else
    {
        cout << "\"exp1\":";
        this->exp1->Dump();
        cout << ",\"exp2\":";
        this->exp2->Dump();
    }
    cout << "}";
}



bool RelAST::is_lval() const
{
    if (this->op == DEFAULT)
        return this->exp1->is_lval();
    return false;
}

void RelAST::Analyze() const
{
    if (this->op == RelAST::DEFAULT)
        this->exp1->Analyze();
    else
    {
        this->exp2->Analyze();
        GENASM(cmd_code::PUSH, CVR(EAX), cmd_val());
        this->exp1->Analyze();
        GENASM(cmd_code::POP, CVR(EDX), cmd_val());
        GENASM(cmd_code::CMP, CVR(EAX), CVR(EDX));
        switch (this->op)
        {
        case RelAST::GE:GENASM(cmd_code::SETGE, CVR(AL), cmd_val()); break;
        case RelAST::LE:GENASM(cmd_code::SETLE, CVR(AL), cmd_val()); break;
        case RelAST::GT:GENASM(cmd_code::SETG, CVR(AL), cmd_val()); break;
        case RelAST::LT:GENASM(cmd_code::SETL, CVR(AL), cmd_val()); break;
        }
        GENASM(cmd_code::MOVZBL, CVR(AL), CVR(EAX));
    }
}
